using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using Crux.Core.Data;
using Crux.Core.MethodEx;
using EFCoreSecondLevelCacheInterceptor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;

namespace Crux.Core.EFCore.Test;
/// <summary>
/// TestUnitOfWork
/// </summary>
public class TestUnitOfWork
{
    private ILogger<TestUnitOfWork> logger;
    public TestUnitOfWork(ILogger<TestUnitOfWork> logger)
    {
        this.logger = logger;
    }

    [Fact]
    public async Task Test()
    {
        // await using var scope = serviceProvider.CreateAsyncScope();

        // var logger = scope.ServiceProvider.GetRequiredService<ILogger<TestUnitOfWork>>();

        logger.LogInformation("1");

        // await using var unitOfWork = scope.ServiceProvider.GetRequiredService<IQueryRepository<TestDbContext>>();

        // await unitOfWork.Context.Database.EnsureCreatedAsync().ConfigureAwait(false);

        // await unitOfWork.Set<TestModel>().AddAsync(new TestModel
        // {
        //     Name = "1"
        // });

        // await unitOfWork.Context.SaveChangesAsync();

        // var model = await unitOfWork.Query<TestModel>().Where(c => !c.Deleted).FirstOrDefaultAsync();
        // if (model is not null)
        // {
        //     unitOfWork.Set<TestModel>().Remove(model);

        //     await unitOfWork.Context.SaveChangesAsync();
        //     Assert.NotNull(model.ServiceProvider);
        //     Assert.Equal(model.ServiceProvider, scope.ServiceProvider);
        // }

        // var cached = EF.CompileQuery((DbContext context, long id) => context.Set<TestModel>()
        //     .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromSeconds(10))
        //     .AsNoTracking().FirstOrDefault(c => c.Id.Equals(id)));
        // foreach (var range in Enumerable.Range(0, 2))
        // {

        // var model = cached(unitOfWork.Context,369526888663842816);
        //var model = unitOfWork.Find<TestModel, long>(369526888663842816);

        // unitOfWork.Update<TestModel>(p => p.Id == 1, c => c.SetProperty(p => p.Deleted, _ => true));
        // }

        // var test = unitOfWork.Context.Database.SqlQueryRaw<TestModel>("SELECT id FROM test_model").ToList();
        // foreach (var range in Enumerable.Range(0, 400000))
        // {
        //     var model = await unitOfWork.Query<TestModel>().Where(c => c.Id == 369526888663842816).FirstOrDefaultAsync();
        // }
    }

    [Fact]
    public void Test2()
    {
        var task = Task.FromResult(1);
        if (task is Task t)
        {
            var propertyInfo = task.GetType().GetProperty("Result");

            if (propertyInfo is not null)
            {
                var _ilGetter = DynamicGetterFactory.CreateUsingIl(propertyInfo);
                var value = _ilGetter(task);

                Console.WriteLine(value);
            }
        }
    }

    [Fact]
    public void Test3()
    {
        var boolean = typeof(ISoftDelete).IsAssignableFrom(typeof(TestModel));

        Console.WriteLine(boolean);
    }
    [Fact]
    public void Test4()
    {
        // 创建参数表达式  // 创建参数表达式
        // var parameter = Expression.Parameter(typeof(SetPropertyCalls<TestModel>), "p");

        // // 创建属性表达式 c.Deleted
        // var propertyExpression = Expression.Parameter(typeof(Func<TestModel, bool>), "Deleted");
        // var property = Expression.Invoke(propertyExpression, Expression.Parameter(typeof(TestModel), "c"));

        // // 创建 SetProperty 方法调用表达式
        // var setPropertyMethod = typeof(SetPropertyCalls<TestModel>).GetMethod("SetProperty");
        // var genericSetPropertyMethod = setPropertyMethod.MakeGenericMethod(typeof(bool));

        // var methodCall = Expression.Call(parameter, genericSetPropertyMethod, propertyExpression, property);

        // // 创建 lambda 表达式体
        // var lambdaBody = Expression.Invoke(methodCall, parameter);

        // // 创建 lambda 表达式
        // var lambda = Expression.Lambda<Func<SetPropertyCalls<TestModel>, SetPropertyCalls<TestModel>>>(lambdaBody, parameter);
        var parameter = Expression.Parameter(typeof(SetPropertyCalls<TestModel>), "p");

        // 创建属性表达式 c.Deleted
        var propertyExpression = Expression.Parameter(typeof(Func<TestModel, bool>), "propertyExpression");
        var property = Expression.Invoke(propertyExpression, Expression.Parameter(typeof(TestModel), "c"));

        // 创建值表达式 c => true
        var valueExpression = Expression.Parameter(typeof(Func<TestModel, bool>), "valueExpression");
        var value = Expression.Invoke(valueExpression, Expression.Parameter(typeof(TestModel), "c"));

        // 创建 SetProperty 方法调用表达式
        var setPropertyMethod = typeof(SetPropertyCalls<TestModel>).GetMethods()
            .Single(m => m.Name == "SetProperty" && m.GetParameters().Length == 2);

        var methodCall = Expression.Call(parameter, setPropertyMethod, propertyExpression, valueExpression);

        // 创建 lambda 表达式体
        var lambdaBody = Expression.Invoke(methodCall, parameter);

        // 创建 lambda 表达式
        var lambda = Expression.Lambda<Func<SetPropertyCalls<TestModel>, SetPropertyCalls<TestModel>>>(lambdaBody, parameter);


        var func = lambda.Compile();


    }
}